package com.zenithmind.library.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.common.result.ResultCode;
import com.zenithmind.library.mapper.BookMapper;
import com.zenithmind.library.mapper.BookReviewMapper;
import com.zenithmind.library.pojo.domain.Book;
import com.zenithmind.library.pojo.domain.BookReview;
import com.zenithmind.library.pojo.dto.BookReviewCreateDTO;
import com.zenithmind.library.pojo.dto.BookReviewUpdateDTO;
import com.zenithmind.library.pojo.query.BookReviewQuery;
import com.zenithmind.library.pojo.vo.BookReviewVO;
import com.zenithmind.library.service.BookReviewService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 图书评价服务实现类
 * 遵循单一职责原则：只负责图书评价相关的业务逻辑
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BookReviewServiceImpl extends ServiceImpl<BookReviewMapper, BookReview> implements BookReviewService {

    private final BookReviewMapper bookReviewMapper;
    private final BookMapper bookMapper;

    @Override
    @Cacheable(value = "bookReviews", key = "'page:' + #query.hashCode()")
    public PageResult<BookReviewVO> getBookReviewPage(BookReviewQuery query) {
        log.info("分页查询图书评价，查询条件：{}", query);

        // 构建查询条件
        LambdaQueryWrapper<BookReview> wrapper = new LambdaQueryWrapper<>();
        
        if (query.getBookId() != null && !query.getBookId().trim().isEmpty()) {
            wrapper.eq(BookReview::getBookId, query.getBookId());
        }
        
        if (query.getUserId() != null && !query.getUserId().trim().isEmpty()) {
            wrapper.eq(BookReview::getUserId, query.getUserId());
        }
        
        if (query.getRating() != null) {
            wrapper.eq(BookReview::getRating, query.getRating());
        }
        
        if (query.getStatus() != null) {
            wrapper.eq(BookReview::getStatus, query.getStatus());
        }
        
        if (query.getContentKeyword() != null && !query.getContentKeyword().trim().isEmpty()) {
            wrapper.like(BookReview::getReviewContent, query.getContentKeyword());
        }
        
        wrapper.orderByDesc(BookReview::getCreateTime);

        // 分页查询
        Page<BookReview> page = new Page<>(query.getCurrent(), query.getSize());
        IPage<BookReview> result = page(page, wrapper);

        // 转换为VO
        List<BookReviewVO> vos = result.getRecords().stream()
                                      .map(this::convertToVO)
                                      .collect(Collectors.toList());

        return PageResult.of(vos, result.getTotal(), result.getCurrent(), result.getSize());
    }

    @Override
    @Cacheable(value = "bookReviews", key = "#id")
    public Result<BookReviewVO> getBookReviewById(String id) {
        log.info("根据ID查询图书评价详情，ID：{}", id);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "评价ID不能为空", null);
        }

        BookReview bookReview = getById(id);
        if (bookReview == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书评价不存在", null);
        }

        BookReviewVO vo = convertToVO(bookReview);
        return Result.success(vo);
    }

    @Override
    public Result<List<BookReviewVO>> getBookReviewsByBookId(String bookId, Integer limit) {
        log.info("根据图书ID查询评价列表，图书ID：{}，限制数量：{}", bookId, limit);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        LambdaQueryWrapper<BookReview> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookReview::getBookId, bookId)
               .eq(BookReview::getStatus, 1) // 只查询已审核通过的评价
               .orderByDesc(BookReview::getCreateTime);

        if (limit != null && limit > 0) {
            wrapper.last("LIMIT " + limit);
        }

        List<BookReview> bookReviews = list(wrapper);
        List<BookReviewVO> vos = bookReviews.stream()
                                           .map(this::convertToVO)
                                           .collect(Collectors.toList());

        return Result.success(vos);
    }

    @Override
    public Result<List<BookReviewVO>> getBookReviewsByUserId(String userId, Integer limit) {
        log.info("根据用户ID查询评价列表，用户ID：{}，限制数量：{}", userId, limit);

        if (userId == null || userId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "用户ID不能为空", null);
        }

        LambdaQueryWrapper<BookReview> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookReview::getUserId, userId)
               .orderByDesc(BookReview::getCreateTime);

        if (limit != null && limit > 0) {
            wrapper.last("LIMIT " + limit);
        }

        List<BookReview> bookReviews = list(wrapper);
        List<BookReviewVO> vos = bookReviews.stream()
                                           .map(this::convertToVO)
                                           .collect(Collectors.toList());

        return Result.success(vos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookReviews", allEntries = true)
    public Result<BookReviewVO> createBookReview(BookReviewCreateDTO createDTO) {
        log.info("创建图书评价，参数：{}", createDTO);

        // 验证图书是否存在
        Book book = bookMapper.selectById(createDTO.getBookId());
        if (book == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书不存在", null);
        }

        // 检查用户是否已评价该图书
        if (hasUserReviewedBook(createDTO.getBookId(), createDTO.getUserId())) {
            return Result.fail(ResultCode.CONFLICT.getCode(), "您已评价过该图书", null);
        }

        BookReview bookReview = new BookReview();
        BeanUtils.copyProperties(createDTO, bookReview);
        bookReview.setId(UUID.randomUUID().toString());
        bookReview.setStatus(0); // 待审核
        bookReview.setLikeCount(0);
        bookReview.setCreateTime(LocalDateTime.now());
        bookReview.setUpdateTime(LocalDateTime.now());

        save(bookReview);

        BookReviewVO vo = convertToVO(bookReview);
        log.info("图书评价创建成功，ID：{}", bookReview.getId());
        return Result.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookReviews", allEntries = true)
    public Result<BookReviewVO> updateBookReview(String id, BookReviewUpdateDTO updateDTO) {
        log.info("更新图书评价，ID：{}，参数：{}", id, updateDTO);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "评价ID不能为空", null);
        }

        BookReview bookReview = getById(id);
        if (bookReview == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书评价不存在", null);
        }

        // 只允许更新内容和评分，其他字段不允许修改
        if (updateDTO.getReviewContent() != null) {
            bookReview.setReviewContent(updateDTO.getReviewContent());
        }
        if (updateDTO.getRating() != null) {
            bookReview.setRating(updateDTO.getRating());
        }
        if (updateDTO.getIsAnonymous() != null) {
            bookReview.setIsAnonymous(updateDTO.getIsAnonymous());
        }
        bookReview.setUpdateTime(LocalDateTime.now());

        updateById(bookReview);

        BookReviewVO vo = convertToVO(bookReview);
        log.info("图书评价更新成功，ID：{}", id);
        return Result.success(vo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookReviews", allEntries = true)
    public Result<Void> deleteBookReview(String id) {
        log.info("删除图书评价，ID：{}", id);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "评价ID不能为空", null);
        }

        BookReview bookReview = getById(id);
        if (bookReview == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书评价不存在", null);
        }

        removeById(id);

        log.info("图书评价删除成功，ID：{}", id);
        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "bookReviews", allEntries = true)
    public Result<Void> batchDeleteBookReviews(List<String> ids) {
        log.info("批量删除图书评价，数量：{}", ids.size());

        if (ids == null || ids.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "评价ID列表不能为空", null);
        }

        removeByIds(ids);

        log.info("批量删除图书评价成功，数量：{}", ids.size());
        return Result.success();
    }

    @Override
    @CacheEvict(value = "bookReviews", allEntries = true)
    public Result<Void> likeReview(String id, String userId) {
        log.info("点赞评价，评价ID：{}，用户ID：{}", id, userId);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "评价ID不能为空", null);
        }

        BookReview bookReview = getById(id);
        if (bookReview == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书评价不存在", null);
        }

        // 增加点赞数
        bookReview.setLikeCount(bookReview.getLikeCount() + 1);
        bookReview.setUpdateTime(LocalDateTime.now());
        updateById(bookReview);

        // 实际项目中，这里应该记录用户点赞关系，避免重复点赞

        log.info("点赞评价成功，评价ID：{}", id);
        return Result.success();
    }

    @Override
    @CacheEvict(value = "bookReviews", allEntries = true)
    public Result<Void> unlikeReview(String id, String userId) {
        log.info("取消点赞评价，评价ID：{}，用户ID：{}", id, userId);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "评价ID不能为空", null);
        }

        BookReview bookReview = getById(id);
        if (bookReview == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书评价不存在", null);
        }

        // 减少点赞数
        if (bookReview.getLikeCount() > 0) {
            bookReview.setLikeCount(bookReview.getLikeCount() - 1);
            bookReview.setUpdateTime(LocalDateTime.now());
            updateById(bookReview);
        }

        log.info("取消点赞评价成功，评价ID：{}", id);
        return Result.success();
    }

    @Override
    public boolean hasUserReviewedBook(String bookId, String userId) {
        LambdaQueryWrapper<BookReview> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BookReview::getBookId, bookId)
               .eq(BookReview::getUserId, userId);
        return count(wrapper) > 0;
    }

    /**
     * 转换为VO对象
     */
    private BookReviewVO convertToVO(BookReview bookReview) {
        BookReviewVO vo = new BookReviewVO();
        BeanUtils.copyProperties(bookReview, vo);

        // 设置关联数据
        try {
            if (bookReview.getBookId() != null) {
                Book book = bookMapper.selectById(bookReview.getBookId());
                if (book != null) {
                    vo.setBookTitle(book.getTitle());
                    vo.setBookCover(book.getCoverImage());
                }
            }

            // 设置状态描述
            vo.setStatusName(getStatusName(bookReview.getStatus()));

        } catch (Exception e) {
            log.warn("获取图书评价关联数据失败，评价ID：{}", bookReview.getId(), e);
        }

        return vo;
    }

    /**
     * 获取状态名称
     */
    private String getStatusName(Integer status) {
        if (status == null) {
            return "未知";
        }

        return switch (status) {
            case 0 -> "待审核";
            case 1 -> "已通过";
            case 2 -> "已拒绝";
            case 3 -> "已删除";
            default -> "未知状态";
        };
    }

    @Override
    @CacheEvict(value = "bookReviews", allEntries = true)
    public Result<Void> reportReview(String id, String userId, String reason) {
        log.info("举报评价，评价ID：{}，用户ID：{}，原因：{}", id, userId, reason);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "评价ID不能为空", null);
        }

        BookReview bookReview = getById(id);
        if (bookReview == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书评价不存在", null);
        }

        // 注意：BookReview实体没有reportCount字段，这里只记录日志
        // 实际项目中应该在单独的举报表中记录举报信息
        bookReview.setUpdateTime(LocalDateTime.now());
        updateById(bookReview);

        // 实际项目中，这里应该记录举报详情到举报表

        log.info("举报评价成功，评价ID：{}", id);
        return Result.success();
    }

    @Override
    @CacheEvict(value = "bookReviews", allEntries = true)
    public Result<Void> auditReview(String id, Integer status, String auditReason) {
        log.info("审核评价，评价ID：{}，状态：{}，原因：{}", id, status, auditReason);

        if (id == null || id.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "评价ID不能为空", null);
        }

        BookReview bookReview = getById(id);
        if (bookReview == null) {
            return Result.fail(ResultCode.NOT_FOUND.getCode(), "图书评价不存在", null);
        }

        bookReview.setStatus(status);
        bookReview.setUpdateTime(LocalDateTime.now());
        updateById(bookReview);

        log.info("审核评价成功，评价ID：{}", id);
        return Result.success();
    }

    @Override
    public Result<BookReviewStatisticsVO> getBookReviewStatistics(String bookId) {
        log.info("获取图书评价统计，图书ID：{}", bookId);

        if (bookId == null || bookId.trim().isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "图书ID不能为空", null);
        }

        try {
            BookReviewStatisticsVO statistics = new BookReviewStatisticsVO();

            // 查询该图书的所有评价
            LambdaQueryWrapper<BookReview> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(BookReview::getBookId, bookId)
                   .eq(BookReview::getStatus, 1); // 只统计已通过的评价

            List<BookReview> reviews = list(wrapper);
            statistics.setTotalReviews(reviews.size());

            if (!reviews.isEmpty()) {
                // 计算平均评分
                double averageRating = reviews.stream()
                                             .mapToInt(BookReview::getRating)
                                             .average()
                                             .orElse(0.0);
                statistics.setAverageRating(Math.round(averageRating * 100.0) / 100.0);

                // 按评分分组统计
                statistics.setFiveStarCount((int) reviews.stream().filter(r -> r.getRating() == 5).count());
                statistics.setFourStarCount((int) reviews.stream().filter(r -> r.getRating() == 4).count());
                statistics.setThreeStarCount((int) reviews.stream().filter(r -> r.getRating() == 3).count());
                statistics.setTwoStarCount((int) reviews.stream().filter(r -> r.getRating() == 2).count());
                statistics.setOneStarCount((int) reviews.stream().filter(r -> r.getRating() == 1).count());

                // 统计点赞数
                statistics.setLikeCount(reviews.stream().mapToInt(BookReview::getLikeCount).sum());
                // 注意：BookReview实体没有reportCount字段，设置为0
                statistics.setReportCount(0);
            } else {
                statistics.setAverageRating(0.0);
                statistics.setFiveStarCount(0);
                statistics.setFourStarCount(0);
                statistics.setThreeStarCount(0);
                statistics.setTwoStarCount(0);
                statistics.setOneStarCount(0);
                statistics.setLikeCount(0);
                statistics.setReportCount(0);
            }

            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取图书评价统计失败，图书ID：{}", bookId, e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "获取统计信息失败", null);
        }
    }

    @Override
    public Result<String> importBookReviews(List<BookReviewCreateDTO> reviews) {
        log.info("导入图书评价数据，数量：{}", reviews.size());

        if (reviews == null || reviews.isEmpty()) {
            return Result.fail(ResultCode.PARAM_ERROR.getCode(), "导入数据不能为空", null);
        }

        int successCount = 0;
        int failCount = 0;
        StringBuilder errorMessages = new StringBuilder();

        for (int i = 0; i < reviews.size(); i++) {
            BookReviewCreateDTO reviewDTO = reviews.get(i);
            try {
                // 数据验证
                if (reviewDTO.getBookId() == null || reviewDTO.getBookId().trim().isEmpty()) {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：图书ID不能为空；");
                    continue;
                }

                if (reviewDTO.getUserId() == null || reviewDTO.getUserId().trim().isEmpty()) {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：用户ID不能为空；");
                    continue;
                }

                // 检查用户是否已评价该图书
                if (hasUserReviewedBook(reviewDTO.getBookId(), reviewDTO.getUserId())) {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：用户已评价过该图书；");
                    continue;
                }

                // 创建评价
                Result<BookReviewVO> createResult = createBookReview(reviewDTO);
                if (createResult.isSuccess()) {
                    successCount++;
                } else {
                    failCount++;
                    errorMessages.append("第").append(i + 1).append("行：").append(createResult.getMsg()).append("；");
                }
            } catch (Exception e) {
                failCount++;
                errorMessages.append("第").append(i + 1).append("行：").append(e.getMessage()).append("；");
                log.error("导入第{}行数据失败", i + 1, e);
            }
        }

        String resultMessage = String.format("导入完成，成功：%d条，失败：%d条", successCount, failCount);
        if (failCount > 0) {
            resultMessage += "。失败原因：" + errorMessages.toString();
        }

        log.info("图书评价数据导入完成，成功：{}条，失败：{}条", successCount, failCount);
        return Result.success(resultMessage);
    }

    @Override
    public Result<String> exportBookReviews(BookReviewQuery query) {
        log.info("导出图书评价数据，查询条件：{}", query);

        try {
            // 1. 查询数据
            if (query == null) {
                query = new BookReviewQuery();
            }

            // 设置较大的分页大小以获取所有数据
            query.setSize(10000); // 最多导出10000条记录
            PageResult<BookReviewVO> pageResult = getBookReviewPage(query);

            if (pageResult == null || pageResult.getRecords() == null || pageResult.getRecords().isEmpty()) {
                return Result.fail(ResultCode.NOT_FOUND.getCode(), "没有找到符合条件的图书评价数据", null);
            }

            // 2. 生成Excel文件路径
            String timestamp = String.valueOf(System.currentTimeMillis());
            String fileName = "book_reviews_export_" + timestamp + ".xlsx";
            String filePath = "/exports/" + fileName;

            // 3. 这里应该实现实际的Excel生成逻辑
            log.info("模拟生成Excel文件，包含{}条记录，文件路径：{}", pageResult.getRecords().size(), filePath);

            String resultMessage = String.format("导出成功，共%d条记录，文件：%s",
                pageResult.getRecords().size(), fileName);

            log.info("图书评价数据导出完成，记录数：{}，文件：{}", pageResult.getRecords().size(), fileName);
            return Result.success(resultMessage);

        } catch (Exception e) {
            log.error("导出图书评价数据失败", e);
            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), "导出失败：" + e.getMessage(), null);
        }
    }
}
